package com.caigou.comm.base.network

import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import java.io.IOException

/**
 * @author #Suyghur.
 * Created on 2021/09/16
 */
class GsonTypeAdapterFactory : TypeAdapterFactory {
    override fun <T : Any?> create(gson: Gson?, type: TypeToken<T>?): TypeAdapter<T> {
        val adapter = gson?.getDelegateAdapter(this, type)
        return object : TypeAdapter<T>() {
            @Throws(IOException::class)
            override fun write(writer: JsonWriter?, value: T) {
                adapter?.write(writer, value)
            }

            @Throws(IOException::class)
            override fun read(reader: JsonReader): T? {
                // Gson库会通过JsonReader对json对象的每个字段进行读取，当发现类型不匹配是抛出异常
                return try {
                    adapter?.read(reader)
                } catch (e: Throwable) {
                    consumeAll(reader)
                    null
                }
            }

            @Throws(IOException::class)
            private fun consumeAll(reader: JsonReader) {
                if (reader.hasNext()) {
                    val peek: JsonToken = reader.peek()
                    when {
                        peek === JsonToken.STRING -> {
                            reader.nextString()
                        }
                        peek === JsonToken.NUMBER -> {
                            reader.nextString()
                        }
                        peek === JsonToken.BOOLEAN -> {
                            reader.nextBoolean()
                        }
                        peek === JsonToken.NAME -> {
                            reader.nextName()
                            consumeAll(reader)
                        }
                        peek === JsonToken.BEGIN_ARRAY -> {
                            reader.beginArray()
                            consumeAll(reader)
                            reader.endArray()
                        }
                        peek === JsonToken.BEGIN_OBJECT -> {
                            reader.beginObject()
                            consumeAll(reader)
                            reader.endObject()
                        }
                        peek === JsonToken.END_ARRAY -> {
                            reader.endArray()
                        }
                        peek === JsonToken.END_OBJECT -> {
                            reader.endObject()
                        }
                        peek === JsonToken.NULL -> {
                            reader.nextNull()
                        }
                    }
                }
            }

        }
    }
}